package com.maybach.workflow.core.processor.impl;


import com.maybach.workflow.common.api.FlowHandlerFactory;
import com.maybach.workflow.common.api.IInterceptor;
import com.maybach.workflow.common.api.WorkFlowContext;
import com.maybach.workflow.common.api.enums.FlowStateEnum;
import com.maybach.workflow.common.api.node.BaseNode;
import com.maybach.workflow.common.api.node.TaskNode;
import com.maybach.workflow.common.model.FlowDO;
import com.maybach.workflow.common.model.FlowTaskActorDO;
import com.maybach.workflow.common.model.FlowTaskDO;
import com.maybach.workflow.core.service.TaskService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

import java.util.List;

/**
 * Created by houenxun on 15/8/13.
 */
public class TaskProcessor extends AbstractProcessor {

    @Autowired
    protected TaskService taskService;

    private List<IInterceptor> runInInterceptor;

    private List<IInterceptor> runOutInInterceptor;

    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Override
    public List<BaseNode> getNextNodes(WorkFlowContext workFlowContext) {

        return super.getCommonNextNodes(workFlowContext);
    }

    @Override
    public boolean runIn(WorkFlowContext workFlowContext) {
        TaskNode taskNode = (TaskNode)workFlowContext.getThisNode();
        FlowDO flowDO = workFlowContext.getThisFlow();
        FlowTaskDO flowTaskDO = new FlowTaskDO();
        flowTaskDO.setDisplayName(taskNode.getDisplayName());
        flowTaskDO.setParentTaskId(super.getParentTaskId(workFlowContext));
        flowTaskDO.setTaskName(taskNode.getName());
        flowTaskDO.setTaskState(FlowStateEnum.init.getStatus());
        flowTaskDO.setFlowId(flowDO.getId());
        flowTaskDO.setTaskType(taskNode.getNodeType().name());
        flowTaskDO.setBizId(flowDO.getBizId());
        flowTaskDO.setBizType(flowDO.getBizType());
        flowRepository.createFlowTask(flowTaskDO);
        workFlowContext.setThisTask(flowTaskDO);

        List<FlowTaskActorDO> taskActors = taskService.getTaskActor(flowTaskDO, taskNode, workFlowContext);
        flowRepository.createTaskActors(taskActors);
        workFlowContext.setTaskActorDOList(taskActors);
        // 执行业务逻辑
        if(CollectionUtils.isNotEmpty(taskNode.getBeforeHandlers())){
            for(String handler : taskNode.getBeforeHandlers()){
                if(StringUtils.isNotBlank(handler)){
                    FlowHandlerFactory.handle(handler, workFlowContext);
                }
            }
        }

        /**
         * 执行创建任务后的额外逻辑 可插拔
         */
        if(CollectionUtils.isNotEmpty(runInInterceptor)){
            for(IInterceptor interceptor : runInInterceptor){
                interceptor.execute(workFlowContext);
            }
        }

        return true;
    }

    @Override
    public void runOut(WorkFlowContext workFlowContext) {
        FlowDO thisFlow = workFlowContext.getThisFlow();
        if(!thisFlow.getFlowState().equals(FlowStateEnum.init.getStatus())){
            flowRepository.updateFlowStatus(thisFlow.getId(), FlowStateEnum.init.getStatus());
        }
        //prepareContext(workFlowContext);
        this.fillTask(workFlowContext);
        super.logFlowTaskHis(workFlowContext.getThisFlow(), workFlowContext.getThisTask(),workFlowContext.getTaskActor() );
        flowRepository.delFlowTaskById(workFlowContext.getThisTask().getId());
        flowRepository.clearTaskActorByTaskId(workFlowContext.getThisTask().getId());
        workFlowContext.setLastTask(workFlowContext.getThisTask());
        // 执行业务逻辑
        TaskNode taskNode = (TaskNode) workFlowContext.getThisNode();
        if(CollectionUtils.isNotEmpty(taskNode.getAfterHandlers())){
            for(String handler : taskNode.getAfterHandlers()){
                if(StringUtils.isNotBlank(handler)){
                    FlowHandlerFactory.handle(handler, workFlowContext);
                }
            }
        }

        /**
         * 执行完成任务后的额外逻辑 可插拔
         */
        if(CollectionUtils.isNotEmpty(runOutInInterceptor)){
            for(IInterceptor interceptor : runOutInInterceptor){
                interceptor.execute(workFlowContext);
            }
        }

        super.noPersistRunOut(workFlowContext);
    }


    private void fillTask(WorkFlowContext workFlowContext){
        if(null == workFlowContext.getThisTask()){
            FlowTaskDO flowTaskDO = flowRepository.getFlowTaskWithName(workFlowContext.getThisFlow().getId(), workFlowContext.getActionName());
            Assert.notNull(flowTaskDO,"flowTaskDO");
            workFlowContext.setThisTask(flowTaskDO);
        }

    }


    public void setRunInInterceptor(List<IInterceptor> runInInterceptor) {
        this.runInInterceptor = runInInterceptor;
    }

    public void setRunOutInInterceptor(List<IInterceptor> runOutInInterceptor) {
        this.runOutInInterceptor = runOutInInterceptor;
    }
}
